//
//  ModelMap.swift
//  Lease_IOS
//
//  Created by Mr.wang on 2018/12/20.
//  Copyright © 2018 Mr.wang. All rights reserved.
//

import Moya
import HandyJSON
import RxSwift

struct BaseModel<T: HandyJSON>: HandyJSON {
    var code: Int = 0
    var data: T = T()
    var msg: String = ""
}

struct NullableBaseModel<T: HandyJSON>: HandyJSON {
    var code: Int = 0
    var data: T?
    var msg: String = ""
}

extension Array: HandyJSON { }
extension Int: HandyJSON { }
extension String: HandyJSON { }

extension Response {
    
    // code，msg，data
    func modelMap<T : HandyJSON>(_ type : T.Type) -> T {
        return JSONDeserializer<T>.deserializeFrom(dict: jsonDictionary) ?? T()
    }
    
}

extension ObservableType where Element == ProgressResponse {
    
    public func modelMap<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
        return self.filter{ $0.completed }
            .map{ $0.response }
            .filterNil()
            .modelMap(T.self)
    }
    
}

extension ObservableType where Element == Response {
    
    public func modelMap<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
        return map{ $0.modelMap(T.self) }
    }
    
    public func dataModelMap<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
        return modelMap(BaseModel<T>.self).map{ $0.data }
    }
    
    public func jsonDictionary() -> Observable<NSDictionary> {
        return map{ $0.jsonDictionary }
    }
    
    public func dataDictionary() -> Observable<NSDictionary>{
        return map{ $0.jsonDictionary.dictionaryValue("data") }
    }
    
}

extension PrimitiveSequence where Trait == SingleTrait, Element == Response {
    
    public func modelMap<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
        return self.asObservable().modelMap(T.self)
    }
    
    public func dataModelMap<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
        return self.asObservable().dataModelMap(T.self)
    }
    
    public func jsonDictionary() -> Observable<NSDictionary> {
        return self.asObservable().jsonDictionary()
    }
    
    public func dataDictionary() -> Observable<NSDictionary>{
        return self.asObservable().dataDictionary()
    }
}
